package com.zoe.app.service;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zoe.app.eneity.RedPackage;
import com.zoe.app.mapper.RedPageMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zoe.Zhang
 * @date 2023/02/03
 * @description
 */
@Service
public class RedPackageServiceImpl {
    private static final String RED_KEY = "red";
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RedPageMapper redPageMapper;

    @Autowired
    private RedissonClient redissonClient;

    public List<RedPackage> getAll() {
        return redPageMapper.selectAll();
    }

    public RedPackage getOne() {
        return redPageMapper.getOne();
    }

    public Map<String, Object> update() {
        Map<String, Object> resMap = MapUtil.newHashMap();
        RedPackage view = (RedPackage) view();
        Integer amount = view.getAmount();
        Integer count = view.getCount();

        if (amount > 0) {
            view.setAmount(amount - 10);
            view.setCount(count + 1);
            redisTemplate.opsForValue().set(RED_KEY, view);
            resMap.put(RED_KEY, view);
            return resMap;
        }
        resMap.put(RED_KEY, "失败");
        return resMap;
    }

    public Map<String, Object> updateLock() {
        RLock lock = redissonClient.getLock(RED_KEY);
        Map<String, Object> resMap = MapUtil.newHashMap();
        try {
            boolean b = lock.tryLock(1, TimeUnit.SECONDS);
            RedPackage view = (RedPackage) view();
            Integer amount = view.getAmount();
            Integer count = view.getCount();
            if (b && amount > 0) {
                view.setAmount(amount - 10);
                view.setCount(count + 1);
                redisTemplate.opsForValue().set(RED_KEY, view);
                resMap.put(RED_KEY, view);
                return resMap;
            }
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (ObjectUtil.isNotNull(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        resMap.put(RED_KEY, "error");
        return resMap;
    }

    public int init() {
        redisTemplate.opsForValue().set(RED_KEY, getOne());
        return 1;
    }

    public Object view() {
        return redisTemplate.opsForValue().get(RED_KEY);
    }
}
